package com.mangocheese.subject.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.jakarta.StatViewServlet;
import com.alibaba.druid.support.jakarta.WebStatFilter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;

/**
 * 自定义DataSource配置文件解析类，初始化Druid的数据源
 * 因为 Druid与Spring Boot的兼容性问题还是比较多的
 * 正常可能无法进行密码解密
 * 本类对应配置文件中 spring.datasource
 */
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
@Data // lombok pom引用
@Slf4j
public class DataSourceConfig {

    private String username;
    private String password;
    private String url;
    private String driverClassName;

    @Data
    private static class DruidConfig{
        private String type;
        private Integer initialSize;
        private Integer minIdle;
        private Integer maxActive;
        private Long maxWait;
        private Long timeBetweenEvictionRunsMillis;
        private Long minEvictableIdleTimeMillis;
        private String validationQuery;
        private Boolean testWhileIdle;
        private Boolean testOnBorrow;
        private Boolean testOnReturn;
        private Boolean poolPreparedStatements;
        private Integer maxPoolPreparedStatementPerConnectionSize;
        private String filters;
        private String connectionProperties;
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid")
    public DruidConfig getDruidConfig(){
        return new DruidConfig();
    }

    @Bean
    @Primary // 设置优先级
    public DataSource druidDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        DruidConfig druidConfig;

        try {
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            druidConfig = getDruidConfig();
            dataSource.setDbType(druidConfig.type);
            dataSource.setInitialSize(druidConfig.initialSize);
            dataSource.setMinIdle(druidConfig.minIdle);
            dataSource.setMaxActive(druidConfig.maxActive);
            dataSource.setMaxWait(druidConfig.maxWait);
            dataSource.setTimeBetweenEvictionRunsMillis(druidConfig.timeBetweenEvictionRunsMillis);
            dataSource.setMinEvictableIdleTimeMillis(druidConfig.minEvictableIdleTimeMillis);
            dataSource.setValidationQuery(druidConfig.validationQuery);
            dataSource.setTestWhileIdle(druidConfig.testWhileIdle);
            dataSource.setTestOnBorrow(druidConfig.testOnBorrow);
            dataSource.setTestOnReturn(druidConfig.testOnReturn);
            dataSource.setPoolPreparedStatements(druidConfig.poolPreparedStatements);
            dataSource.setMaxPoolPreparedStatementPerConnectionSize(druidConfig.maxPoolPreparedStatementPerConnectionSize);
            dataSource.setFilters(druidConfig.filters);
            dataSource.setConnectionProperties(druidConfig.connectionProperties);
        } catch (SQLException e) {
            log.error("Druid初始化异常！", e);
        }

        log.info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Druid DataSource Init>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

        return dataSource;

    }

    // 向IOC容器添加ServletRegistrationBean组件，开启druid监控功能
    @Bean
    @Primary
    public ServletRegistrationBean statViewServlet() {
        StatViewServlet statViewServlet = new StatViewServlet();
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean =
                // druid监控的访问页面是/druid/*
                new ServletRegistrationBean<>(statViewServlet, "/druid/*");

        // 开启监控页面的访问登录账号和密码
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "admin");

        return servletRegistrationBean;
    }

    // 开启Web应用菜单功能，让druid进行Web应用的统计
    @Bean
    @Primary
    public FilterRegistrationBean webStatFilter() {
        WebStatFilter webStatFilter = new WebStatFilter();

        FilterRegistrationBean<WebStatFilter> filterRegistrationBean =
                new FilterRegistrationBean<>(webStatFilter);
        // 设置统计的Web URL
        filterRegistrationBean.setUrlPatterns(List.of("/*"));
        // 设置排除的Web URL
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");

        return filterRegistrationBean;
    }

}
